package websocket

import (
	"database/sql"
	"encoding/json"
	"log"

	"tuiwen-go/internal/api"
	"tuiwen-go/internal/config"
	"tuiwen-go/internal/db"
	"tuiwen-go/internal/utils"

	"archive/zip"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"

	"github.com/google/uuid"
)

// taskDraftHandler handles messages of type 5.
func taskDraftHandler(c *Client, data json.RawMessage) {
	log.Printf("Client %s: Handling Draft Task, Data: %s", c.ID, string(data))

	var taskData struct {
		ProjectID   string `json:"project_id"`
		ProjectName string `json:"project_name"`
	}

	if err := json.Unmarshal(data, &taskData); err != nil {
		log.Printf("Client %s: Error unmarshalling draft task data: %v", c.ID, err)
		sendMessage(c, api.WxJSONResponse{Code: -1, Msg: "Invalid draft task data format"})
		return
	}

	if taskData.ProjectID == "" {
		sendMessage(c, api.WxJSONResponse{Code: -1, Msg: "项目ID不能为空"})
		return
	} else {
		sqlQuery := "SELECT name FROM project WHERE id = ? "
		db.QueryRow(sqlQuery, taskData.ProjectID).Scan(&taskData.ProjectName)

	}

	// 查询文案时，ProjectID 类型为 string，需调整查询参数
	sqlQuery := "SELECT content, image, audio, audio_duration FROM text WHERE project_id = ? order by id"
	rows, err := db.Query(sqlQuery, taskData.ProjectID)
	if err != nil {
		log.Printf("Client %s: Error querying text for draft task: %v", c.ID, err)
		sendMessage(c, api.WxJSONResponse{Code: -1, Msg: "查询文案失败"})
		return
	}
	defer rows.Close()

	var draftDetails []map[string]interface{}

	for rows.Next() {
		var content sql.NullString
		var image sql.NullString
		var audio sql.NullString
		var audio_duration sql.NullInt64
		err := rows.Scan(&content, &image, &audio, &audio_duration)
		if err != nil {
			log.Printf("Client %s: Error scanning text row for draft task: %v", c.ID, err)
			continue
		}

		item := make(map[string]interface{})
		if content.Valid {
			item["content"] = content.String
		} else {
			item["content"] = ""
		}
		if image.Valid {
			item["image"] = image.String
		} else {
			item["image"] = ""
		}
		if audio.Valid {
			item["audio"] = audio.String
		} else {
			item["audio"] = ""
		}
		item["audio_duration"] = 0
		if audio_duration.Valid {
			item["audio_duration"] = int(audio_duration.Int64)
		}

		draftDetails = append(draftDetails, item)
	}

	if err = rows.Err(); err != nil {
		log.Printf("Client %s: Error iterating text rows for draft task: %v", c.ID, err)
		sendMessage(c, api.WxJSONResponse{Code: -1, Msg: "处理文案数据失败"})
		return
	}

	if len(draftDetails) == 0 {
		sendMessage(c, api.WxJSONResponse{Code: 0, Msg: "没有文案可用于生成草稿"})
		return
	}

	// 调用生成草稿函数，传入 projectID 字符串
	generatedDraftPath, err := generateDraft(draftDetails, taskData.ProjectID+"_"+taskData.ProjectName)
	if err != nil {
		log.Printf("Client %s: Error generating draft for project ID %s: %v", c.ID, taskData.ProjectID, err)
		sendMessage(c, api.WxJSONResponse{Code: -1, Msg: "生成草稿失败"})
		return
	}

	// 更新项目表，projectID 为字符串
	sqlUpdate := "UPDATE project SET draft = ? WHERE id = ?"
	_, err = db.Exec(sqlUpdate, generatedDraftPath, taskData.ProjectID)
	if err != nil {
		log.Printf("Client %s: Error updating draft path for project ID %s: %v", c.ID, taskData.ProjectID, err)
		sendMessage(c, api.WxJSONResponse{Code: -1, Msg: "更新草稿路径失败"})
		return
	}

	sendMessage(c, api.WxJSONResponse{Code: 0, Msg: "草稿生成成功"})
}

func generateDraft(draft_data []map[string]interface{}, projectName string) (string, error) {

	draft_removable_storage_device, ok := config.GetSetting("draft_removable_storage_device")
	if !ok {
		log.Printf("获取 draft_removable_storage_device 设置失败: draft_removable_storage_device not found in cache")
		draft_removable_storage_device = "" // Fallback to empty string or default URL
	}
	draft_root_path, ok := config.GetSetting("draft_root_path")
	if !ok {
		log.Printf("获取 draft_root_path 设置失败: draft_root_path not found in cache")
		draft_root_path = "" // Fallback to empty string or default URL
	}
	draft_cover := "draft_cover.jpg"
	draft_dir_name := projectName

	projectRoot, err := os.Getwd()
	if err != nil {
		return "", fmt.Errorf("获取当前工作目录失败: %w", err)
	}

	templatePath := filepath.Join(projectRoot, "templates")

	// 读取并解析 draft_meta_info.template.json
	metaInfoPath := filepath.Join(templatePath, "draft_meta_info.template.json")
	metaInfoBytes, err := ioutil.ReadFile(metaInfoPath)
	if err != nil {
		return "", fmt.Errorf("读取 meta info 模板失败: %w", err)
	}

	var metaInfo map[string]interface{}
	if err := json.Unmarshal(metaInfoBytes, &metaInfo); err != nil {
		return "", fmt.Errorf("解析 meta info 模板失败: %w", err)
	}
	// 填充 metaInfo
	metaInfo["draft_name"] = projectName
	metaInfo["draft_id"] = uuid.New().String()
	metaInfo["draft_fold_path"] = filepath.Join(draft_root_path, projectName)
	metaInfo["draft_cover"] = draft_cover
	metaInfo["draft_removable_storage_device"] = draft_removable_storage_device
	metaInfo["draft_root_path"] = draft_root_path

	destPath := filepath.Join("./public/drafts", draft_dir_name)
	// 检查目录是否存在，不存在则创建
	if _, err := os.Stat(destPath); os.IsNotExist(err) {
		if err := os.MkdirAll(destPath, 0755); err != nil {
			return "", fmt.Errorf("创建目录失败: %w", err)
		}
	}

	// 复制第一张图片作为封面
	if len(draft_data) > 0 && draft_data[0]["image"] != "" {
		srcPath := filepath.Join(projectRoot, draft_data[0]["image"].(string))
		dstPath := filepath.Join(destPath, "draft_cover.jpg")

		srcFile, err := os.Open(srcPath)
		if err != nil {
			return "", fmt.Errorf("打开源图片文件失败: %w", err)
		}
		defer srcFile.Close()

		dstFile, err := os.Create(dstPath)
		if err != nil {
			return "", fmt.Errorf("创建目标图片文件失败: %w", err)
		}
		defer dstFile.Close()

		if _, err := io.Copy(dstFile, srcFile); err != nil {
			return "", fmt.Errorf("复制图片文件失败: %w", err)
		}
	}
	// 读取并解析 draft_content.template.json
	contentPath := filepath.Join(templatePath, "draft_content.template.json")
	contentBytes, err := ioutil.ReadFile(contentPath)
	if err != nil {
		return "", fmt.Errorf("读取 content 模板失败: %w", err)
	}

	var draft_content map[string]interface{}
	if err := json.Unmarshal(contentBytes, &draft_content); err != nil {
		return "", fmt.Errorf("解析 content 模板失败: %w", err)
	}
	// 设置draft_content的ID
	draft_content["id"] = uuid.New().String()

	// 初始化各种空数组
	audios := []interface{}{}
	beats := []interface{}{}
	canvases := []interface{}{}
	sound_channel_mappings := []interface{}{}
	speeds := []interface{}{}
	videos := []interface{}{}
	tracks := []interface{}{}

	// 添加轨道
	// 这里需要实现template_tracks函数或直接创建轨道对象
	videoTrack := utils.TemplateTracks()
	audioTrack := utils.TemplateTracks()

	// 设置轨道类型
	videoTrack["type"] = "video"
	audioTrack["type"] = "audio"

	// 将轨道添加到tracks切片
	tracks = append(tracks, videoTrack)
	tracks = append(tracks, audioTrack)

	// 设置draft_content的tracks属性
	draft_content["tracks"] = tracks

	// 初始化视频和音频片段数组
	segments_video := []interface{}{}
	segments_audio := []interface{}{}
	start := 0

	for i, item := range draft_data {
		// 获取音频时长，如果不存在则使用默认值
		var duration int = 5000000 // 默认5秒
		if audioDuration, ok := item["audio_duration"]; ok {
			// 根据类型进行适当的转换
			switch v := audioDuration.(type) {
			case int64:
				duration = int(v)
			case int:
				duration = v
			case float64:
				duration = int(v)
			default:
				log.Printf("音频时长类型不支持: %T", audioDuration)
			}
		}

		// 图像操作
		imageValue := utils.TemplateMaterials()
		imageDirPath := filepath.Join(destPath, "image")
		if _, err := os.Stat(imageDirPath); os.IsNotExist(err) {
			if err := os.MkdirAll(imageDirPath, 0755); err != nil {
				return "", fmt.Errorf("创建图像目录失败: %w", err)
			}
		}

		// 复制图像文件
		if imgPath, ok := item["image"].(string); ok && imgPath != "" {
			srcImagePath := filepath.Join(projectRoot, imgPath)
			dstImagePath := filepath.Join(imageDirPath, fmt.Sprintf("%d.jpg", i))

			srcImageFile, err := os.Open(srcImagePath)
			if err != nil {
				log.Printf("打开源图像文件失败: %v", err)
				continue
			}
			defer srcImageFile.Close()

			dstImageFile, err := os.Create(dstImagePath)
			if err != nil {
				log.Printf("创建目标图像文件失败: %v", err)
				srcImageFile.Close()
				continue
			}
			defer dstImageFile.Close()

			if _, err := io.Copy(dstImageFile, srcImageFile); err != nil {
				log.Printf("复制图像文件失败: %v", err)
				continue
			}

			// 设置图像素材属性
			imageValue["duration"] = duration
			imageValue["extra_info"] = fmt.Sprintf("%d.jpg", i)
			imageValue["file_Path"] = filepath.Join(draft_root_path, draft_dir_name, "image", fmt.Sprintf("%d.jpg", i))
			imageValue["roughcut_time_range"].(map[string]int)["duration"] = duration
			imageValue["metetype"] = "photo"

			// 音频操作
			audioValue := utils.TemplateMaterials()
			audioDirPath := filepath.Join(destPath, "audio")
			if _, err := os.Stat(audioDirPath); os.IsNotExist(err) {
				if err := os.MkdirAll(audioDirPath, 0755); err != nil {
					return "", fmt.Errorf("创建音频目录失败: %w", err)
				}
			}

			// 复制音频文件（如果存在）
			if audioPath, ok := item["audio"].(string); ok && audioPath != "" {
				srcAudioPath := filepath.Join(projectRoot, audioPath)
				dstAudioPath := filepath.Join(audioDirPath, fmt.Sprintf("%d.mp3", i))

				srcAudioFile, err := os.Open(srcAudioPath)
				if err != nil {
					log.Printf("打开源音频文件失败: %v", err)
				} else {
					defer srcAudioFile.Close()

					dstAudioFile, err := os.Create(dstAudioPath)
					if err != nil {
						log.Printf("创建目标音频文件失败: %v", err)
					} else {
						defer dstAudioFile.Close()

						if _, err := io.Copy(dstAudioFile, srcAudioFile); err != nil {
							log.Printf("复制音频文件失败: %v", err)
						}
					}
				}

				// 设置音频素材属性
				audioValue["duration"] = duration
				audioValue["extra_info"] = fmt.Sprintf("%d.mp3", i)
				audioValue["file_Path"] = filepath.Join(draft_root_path, draft_dir_name, "./audio", fmt.Sprintf("%d.mp3", i))
				audioValue["roughcut_time_range"].(map[string]int)["duration"] = duration
				audioValue["metetype"] = "music"

				// 添加素材到draft_meta_info
				if materials, ok := metaInfo["draft_materials"].([]interface{}); ok && len(materials) > 0 {
					if materialValues, ok := materials[0].(map[string]interface{})["value"].([]interface{}); ok {
						materials[0].(map[string]interface{})["value"] = append(materialValues, imageValue, audioValue)
					}
				}

				// 创建并添加模板
				audiosTemplate := utils.TemplateAudios()
				audiosTemplate["local_material_id"] = audioValue["id"]
				audiosTemplate["name"] = audioValue["extra_info"]
				audiosTemplate["path"] = audioValue["file_Path"]
				audios = append(audios, audiosTemplate)

				beatsTemplate := utils.TemplateBeats()
				beats = append(beats, beatsTemplate)

				canvasesTemplate := utils.TemplateCanvases()
				canvases = append(canvases, canvasesTemplate)

				soundChannelMapping1 := utils.TemplateSoundChannelMappings()
				soundChannelMapping2 := utils.TemplateSoundChannelMappings()
				sound_channel_mappings = append(sound_channel_mappings, soundChannelMapping1, soundChannelMapping2)

				speed1 := utils.TemplateSpeeds()
				speed2 := utils.TemplateSpeeds()
				speeds = append(speeds, speed1, speed2)

				videosTemplate := utils.TemplateVideos()
				videosTemplate["duration"] = duration
				videosTemplate["material_name"] = imageValue["extra_info"]
				videosTemplate["path"] = imageValue["file_Path"]
				videosTemplate["type"] = "photo"
				videosTemplate["width"] = 800
				videosTemplate["height"] = 450
				videos = append(videos, videosTemplate)

				// 创建视频和音频片段
				segmentsVideoTemplate := utils.TemplateSegments()
				segmentsAudioTemplate := utils.TemplateSegments()

				// 设置视频片段属性
				extraMaterialRefs1 := []interface{}{
					speed1["id"],
					canvasesTemplate["id"],
					soundChannelMapping1["id"],
				}
				segmentsVideoTemplate["extra_material_refs"] = extraMaterialRefs1
				segmentsVideoTemplate["material_id"] = videosTemplate["id"]
				segmentsVideoTemplate["source_timerange"] = map[string]interface{}{
					"duration": duration,
					"start":    0,
				}
				segmentsVideoTemplate["target_timerange"] = map[string]interface{}{
					"duration": duration,
					"start":    start,
				}
				segments_video = append(segments_video, segmentsVideoTemplate)

				// 设置音频片段属性
				extraMaterialRefs2 := []interface{}{
					speed2["id"],
					beatsTemplate["id"],
					soundChannelMapping2["id"],
				}
				segmentsAudioTemplate["extra_material_refs"] = extraMaterialRefs2
				segmentsAudioTemplate["material_id"] = audiosTemplate["id"]
				segmentsAudioTemplate["source_timerange"] = map[string]interface{}{
					"duration": duration,
					"start":    0,
				}
				segmentsAudioTemplate["target_timerange"] = map[string]interface{}{
					"duration": duration,
					"start":    start,
				}
				segments_audio = append(segments_audio, segmentsAudioTemplate)

				start += duration
			}
		}
	}
	draft_content["duration"] = start
	draft_content["materials"].(map[string]interface{})["audios"] = audios
	draft_content["materials"].(map[string]interface{})["beats"] = beats
	draft_content["materials"].(map[string]interface{})["canvases"] = canvases
	draft_content["materials"].(map[string]interface{})["sound_channel_mappings"] = sound_channel_mappings
	draft_content["materials"].(map[string]interface{})["speeds"] = speeds
	draft_content["materials"].(map[string]interface{})["videos"] = videos
	draft_content["tracks"].([]interface{})[0].(map[string]interface{})["segments"] = segments_video
	draft_content["tracks"].([]interface{})[1].(map[string]interface{})["segments"] = segments_audio

	// 检查目录是否存在，不存在则创建
	if _, err := os.Stat(destPath); os.IsNotExist(err) {
		if err := os.MkdirAll(destPath, 0755); err != nil {
			return "", fmt.Errorf("创建草稿目录失败: %w", err)
		}
	}

	// 序列化并写入meta_info文件
	metaInfoBytes, err = json.Marshal(metaInfo)
	if err != nil {
		return "", fmt.Errorf("序列化meta_info失败: %w", err)
	}
	metaPath := filepath.Join(destPath, "draft_meta_info.json")
	if err := ioutil.WriteFile(metaPath, metaInfoBytes, 0644); err != nil {
		return "", fmt.Errorf("写入meta_info文件失败: %w", err)
	}

	// 序列化并写入content文件
	contentBytes, err = json.Marshal(draft_content)
	if err != nil {
		return "", fmt.Errorf("序列化content失败: %w", err)
	}
	contentPath = filepath.Join(destPath, "draft_content.json")
	if err := ioutil.WriteFile(contentPath, contentBytes, 0644); err != nil {
		return "", fmt.Errorf("写入content文件失败: %w", err)
	}

	// 创建zip文件
	zipPath := destPath + ".zip"
	if err := zipFolder(destPath, zipPath); err != nil {
		return "", fmt.Errorf("创建zip文件失败: %w", err)
	}

	return filepath.Join("/public/drafts", draft_dir_name+".zip"), nil
}

// zipFolder 将指定文件夹压缩为zip文件
func zipFolder(source, target string) error {
	// 创建zip文件
	zipFile, err := os.Create(target)
	if err != nil {
		return err
	}
	defer zipFile.Close()

	// 创建zip writer
	archive := zip.NewWriter(zipFile)
	defer archive.Close()

	// 遍历源文件夹
	return filepath.Walk(source, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}

		// 获取文件头信息
		header, err := zip.FileInfoHeader(info)
		if err != nil {
			return err
		}

		// 设置压缩方法
		header.Method = zip.Deflate

		// 设置相对路径
		relPath, err := filepath.Rel(source, path)
		if err != nil {
			return err
		}
		if relPath == "." {
			return nil // 跳过根目录
		}

		if info.IsDir() {
			header.Name = relPath + "/" // 确保目录路径以/结尾
			_, err = archive.CreateHeader(header)
			return err
		}

		header.Name = relPath

		// 创建文件条目并写入数据
		writer, err := archive.CreateHeader(header)
		if err != nil {
			return err
		}

		file, err := os.Open(path)
		if err != nil {
			return err
		}
		defer file.Close()

		_, err = io.Copy(writer, file)
		return err
	})
}
